package br.com.petsis.funcionalidades.auditoria;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.persistence.EntityManager;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.Scope;

import br.com.petsis.entity.Auditoria;
import br.com.petsis.entity.Empresa;
import br.com.petsis.entity.Usuario;
import br.com.petsis.enumerations.TipoOperacaoEnum;

@Name("auditoriaController")
@AutoCreate
@Scope(ScopeType.CONVERSATION)
public class AuditoriaController {
	
	@In(create=true)
	private EntityManager entityManager;
	
	private Auditoria auditoria;
	
	@In(required=false)
	Usuario usuarioLogado;
	
	@In(required=false)
    private Empresa empresaSessao;

	public Auditoria getAuditoria() {
		return auditoria;
	}

	public void setAuditoria(Auditoria auditoria) {
		this.auditoria = auditoria;
	}
	
	public void registraLogAuditoria(Object classe, TipoOperacaoEnum tipoOperacao){
		auditoria = new Auditoria();
		Table annotationTable = (Table)classe.getClass().getAnnotation(Table.class);
		auditoria.setDscTabela(annotationTable.name());
		auditoria.setDscUsuario(usuarioLogado.getDscNome()+" ID:"+usuarioLogado.getIdUsuario());
		auditoria.setDtaOperacao(new Date());
		auditoria.setTpoOperacao(tipoOperacao.getId());
		auditoria.setEmpresa(empresaSessao);
//		if(!tipoOperacao.equals(TipoOperacaoEnum.EXCLUSAO)){
			for(Method metodo : classe.getClass().getMethods()){
				if(metodo.isAnnotationPresent(Id.class)){
					Object value = null;
					try {
						value = metodo.invoke(classe);
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					} catch (InvocationTargetException e) {
						e.printStackTrace();
					}
					if(value == null){
						return;
					}else{
						auditoria.setIdRegistro((Integer)value);
					}
				}
			}
//		}
		entityManager.merge(auditoria);
//		entityManager.flush();
	}
	
	public void registraLogAuditoria(Object classe, TipoOperacaoEnum tipoOperacao, String dadosAntigos){
		auditoria = new Auditoria();
		Table annotationTable = (Table)classe.getClass().getAnnotation(Table.class);
		auditoria.setDscTabela(annotationTable.name());
		auditoria.setDscUsuario(usuarioLogado != null ? usuarioLogado.getDscNome()+" ID:"+usuarioLogado.getIdUsuario() : "DESCONHECIDO");
		auditoria.setDtaOperacao(new Date());
		auditoria.setTpoOperacao(tipoOperacao.getId());
		auditoria.setDscDadosAntigos(dadosAntigos);
		auditoria.setDscDadosAtuais(recuperaDadosConcatenados(classe));
		auditoria.setEmpresa(empresaSessao);
//		if(!tipoOperacao.equals(TipoOperacaoEnum.EXCLUSAO)){
		for(Method metodo : classe.getClass().getMethods()){
			if(metodo.isAnnotationPresent(Id.class)){
				Object value = null;
				try {
					value = metodo.invoke(classe);
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				}
				if(value == null){
					return;
				}else{
					auditoria.setIdRegistro((Integer)value);
				}
			}
		}
//		}
		entityManager.merge(auditoria);
//		entityManager.flush();
	}
	
	public String recuperaDadosConcatenados(Object classe){
		StringBuilder retorno = new StringBuilder();
		for(Method metodo : classe.getClass().getMethods()){
			if(!metodo.isAnnotationPresent(Transient.class) && 
					!metodo.isAnnotationPresent(OneToOne.class) &&
					!metodo.isAnnotationPresent(OneToMany.class) &&
//					!metodo.isAnnotationPresent(ManyToOne.class) &&
					metodo.getName().startsWith("get")){
				retorno.append("[");
				retorno.append(metodo.getName().replace("get", ""));
				retorno.append(":");
				Object valor = null;
				try {
					valor = metodo.invoke(classe);
					if(valor != null){
						if(metodo.isAnnotationPresent(JoinColumn.class)){
							for(Method m2 : valor.getClass().getMethods()){
								if(m2.isAnnotationPresent(Id.class)){
									valor = m2.invoke(valor);
								}
							}
						}
						if(valor instanceof Date){
							SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm");
							valor = sdf.format(valor);
						}
					}
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				retorno.append(valor != null ? valor.toString() : null);
				retorno.append("]");
			}
		}
		return retorno.toString();
	}
	
	public static String compararDados(String dadosAntigos, String dadosAtuais){
		StringBuilder retorno = new StringBuilder();
		retorno.append("<table border='1' width='100%' rules='cols'><tr><th align='center'>Coluna</th><th align='center'>Valor Antigo</th><th align='center'>Valor Atual</th></tr>");
		if(dadosAntigos == null || dadosAtuais == null){
			return null;
		}
		int index = -1;
		while(dadosAntigos.indexOf("]", ++index) > -1){
			String sub = dadosAntigos.substring(index, dadosAntigos.indexOf("]", index));
			index = dadosAntigos.indexOf("]", index);
			if(index == -1){
				break;
			}
			sub = sub.replace("]", "");
			sub = sub.replace("[", "");
			if(sub.indexOf(":") == -1){
				continue;
			}
			String coluna = sub.substring(0,sub.indexOf(":"));
			String valor = sub.substring(sub.indexOf(":")+1,sub.length());
			int index2 = -1;
			while(dadosAtuais.indexOf("]", ++index2) > -1){
				String sub2 = dadosAtuais.substring(index2, dadosAtuais.indexOf("]", index2));
				index2 = dadosAtuais.indexOf("]", index2);
				if(index2 == -1){
					break;
				}
				sub2 = sub2.replace("]", "");
				sub2 = sub2.replace("[", "");
				if(sub2.indexOf(":") == -1){
					continue;
				}
				String coluna2 = sub2.substring(0,sub2.indexOf(":"));
				String valor2 = sub2.substring(sub2.indexOf(":")+1,sub2.length());
				if(coluna2.equalsIgnoreCase(coluna) && !valor.equalsIgnoreCase(valor2)){
					retorno.append("<tr><td>");
					retorno.append(coluna);
					retorno.append("</td><td align='center'>");
					retorno.append(valor);
					retorno.append("</td><td align='center'>");
					retorno.append(valor2);
					retorno.append("</td></tr>");
				}
			}
		}
		retorno.append("</table>");
		return retorno.toString();
	}
}
